<?php
/**
 * 创建人 : Forpastime
 * 创建时间: 2023/3/31 15:52
 * 个人主页 : http://forpastime.com
 */

namespace App\Controller\Admin;

use League\Flysystem\Filesystem;
use App\Model\SystemSetting;
use App\Utils\Result;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Filesystem\FilesystemFactory;
use Hyperf\HttpServer\Annotation\AutoController;
use App\Service\FileService;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Redis\Redis;
use Hyperf\Utils\ApplicationContext;
use App\Middleware\Auth\AdminTokenMiddleware;
use App\Middleware\Auth\AdminPowerMiddleware;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;
use App\Annotation\AdminNode;

/**
 * @AdminNode(name="文件管理",isMenu="1",sort=19,style="layui-icon-carousel")
 * @Middlewares({
 *      @Middleware(AdminTokenMiddleware::class),
 *      @Middleware(AdminPowerMiddleware::class)
 * })
 * @AutoController(prefix="admin/file")
 */
class FileController
{
    /**
     * @Inject()
     * @var FileService
     */
    protected $fileService;

    /**
     * @Inject()
     * @var FileSystem
     */
    protected $fileSystem;

    /**
     * @Inject()
     * @var FilesystemFactory
     */
    protected $fileSystemFactory;

    /**
     * @var RequestInterface
     * @Inject()
     */
    protected $request;

    /**
     * @AdminNode(name="上传文件列表",isMenu="1")
     * @return mixed
     */
    public function index()
    {
        $param = $this->request->all();
        $where = [];
        if(isset($param['created_at']) && !empty($param['created_at'])){
            $start = strtotime(explode('~',$param['created_at'])[0]);
            $end =  strtotime(explode('~',$param['created_at'])[1]);
            $where[] = ['created_at','>=',$start];
            $where[] = ['created_at','<=',$end];
        }
        if(isset($param['category_id'])&& $param['category_id']!=''){
            $where[] = ['category_id','=',$param['category_id']];
        }
        if(isset($param['media_type'])&& $param['media_type']!=''){
            $where[] = ['media_type','=',$param['media_type']];
        }
        if(isset($param['store_type'])&& $param['store_type']!=''){
            $where[] = ['store_type','=',$param['store_type']];
        }
        if(isset($param['status'])&& $param['status']!=''){
            $where[] = ['status','=',$param['status']];
        }else{
            $where[] = ['status','=',1];
        }
        $res = $this->fileService->getList($where,'*',intval($param['limit']));
        return Result::success($res);
    }

    /**
     * @AdminNode(name="文件详情",isMenu="0")
     *
     * 根据id获取单条信息
     * @param $id
     * @return mixed
     */
    public function getOne()
    {
        $id = $this->request->input('id');

        $res = $this->fileService->getOne([['id','=',$id]]);
        return Result::success($res);
    }

    /**
     * @AdminNode(name="删除文件",isMenu="0")
     *
     * 删除
     * @param $id
     */
    public function del()
    {
        $param = $this->request->all();

        $ids = array_column($param['data'],'id');
        $res = $this->fileService->del($ids);
        return Result::success();
    }

    /**
     * @AdminNode(name="文件分类",isMenu=1)
     */
    public function category()
    {
        $param = $this->request->all();
        $res = $this->fileService->getAllCategory([],$param['limit']);
        return Result::success($res);
    }
    /**
     * @AdminNode(name="添加分类",isMenu="0")
     */
    public function addCategory()
    {
        $param = $this->request->all();
        if($this->request->isMethod('post')){
            if(isset($param['id']) && empty($param['id'])){
                unset($param['id']);
            }
            $res = $this->fileService->addCategory($param);
        }
        if(isset($param['id']) && !empty($param['id'])){
            $res = $this->fileService->getCategory([['id','=',$param['id']]]);
        }
        return Result::success($res);
    }
    /**
     * @AdminNode(name="获取文件分类",isMenu="0")
     *
     * 获取分类列表
     * @return mixed
     */
    public function getCategory()
    {
        $res = $this->fileService->getCategory([['status','=',1]]);
        return Result::success($res);
    }

    /**
     * @AdminNode(name="文件上传",isMenu="0")
     * @return mixed
     */
    public function upload()
    {
        if($this->request->isMethod('post')){
            $file = $this->request->file('file');
            $categoryId = $this->request->input('category_id',0);

            $res = $this->uploadAction($file,$categoryId);

            if($res['id']>0){
                return Result::success($res);
            }else{
                return Result::error('上传失败');
            }
        }else{
            return Result::success();
        }

    }

    public function uploadAction($file,$categoryId){
        $storage = for_storage_config();

        //验证文件后缀
        //$suffix = for_get_file_extension($this->request->file('file'));
        $suffix = strtolower($file->getExtension());
        if (! in_array(strtolower($suffix), array_merge(explode(',',$storage['video_suffix']),explode(',',$storage['file_suffix']),explode(',',$storage['image_suffix'])))) {
            return Result::error('暂不支持文件类型：'.$suffix);
        }
        $md5 = md5($file->getStream());
        //检查文件是否存在
        $exist = $this->fileService->checkExist([['store_type','=',$storage['storage_type']],['md5','=',md5($file->getStream())]]);
        if(!empty($exist)){
            return $exist;
        }
        switch($storage['storage_type']){
            case 1://本地
                $data = $this->localUplaod($file,$suffix,md5($file->getStream()));
                break;
            case 2://阿里oss
                $data = $this->aliyunOss($file,$suffix,md5($file->getStream()));
                $data['url'] = $storage['protocol'].$storage['bucket'].'.'.$storage['endpoint'].$data['url'];//env('OSS_PROTOCOL') . env('OSS_BUCKET') . '.' . env('OSS_ENDPOINT') . '/' .
                break;
            case 3://七牛云
                $data = $this->qiniuUpload($file,$suffix,md5($file->getStream()));
                $data['url'] = $storage['protocol'].$storage['endpoint'].$data['url'];
                break;
            default:
                return Result::error('未配置当前上传方式');
                break;
        }
        //上传文件入库
        $data['category_id'] = $categoryId;
        $data['store_type'] = $storage['storage_type'];
        $mediaType = $file->getClientMediaType();
        $data['media_type'] = strpos($mediaType,'image')!==false?1:(strpos($mediaType,'audio')!==false?3:(strpos($mediaType,'application/x-')!==false?5:((strpos($mediaType,'application')!==false||strpos($mediaType,'text')!==false)?4:2)));

        //防止重复写入库
        $one = $this->fileService->getOne(['md5'=>$md5]);
        if($one){
            $data['id'] = $one['id'];
        }else{
            $data['id'] = $this->fileService->add($data);
        }
        //显示图片样式处理
        if(in_array(strtolower($suffix),explode(',',$storage['image_suffix']))){
            $data['url'].=$storage['style'];
        }

        return $data;
    }
    /**
     * 本地上传
     * @param $file
     * @return bool
     */
    public function localUplaod($file,$suffix,$md5='')
    {
        if(empty($file)){
            return false;
        }
        $stream = fopen($file->getRealPath(), 'r+');
        if($md5=='') $md5 = time() . mt_rand(1000, 9999);
        $path = 'uploads/'.date('Ymd') .'/'. $md5 . '.' . $suffix;

        $res['name'] = $file->getClientFilename();
        $res['url'] =  '/'.$path;
        $res['md5'] = $md5;
        $res['size'] =$file->getSize();
        if(in_array($suffix,['jpg','jpeg','gif','png','ico'])){
            $info = getimagesize($file->getRealPath());
            $res['width'] = $info[0];
            $res['height'] = $info[1];
        }
        $this->fileSystem->writeStream(
            $path,
            $stream
        );

        fclose($stream);
        return $res;
    }

    public function aliyunOss($file,$suffix,$md5='')
    {
        if (empty($file)) {
            return false;
        }
        $oss = $this->fileSystemFactory->get('oss');
        if($md5=='') $md5 = time() . mt_rand(1000, 9999);
        $path = 'uploads/'.date('Ymd') .'/'. $md5 . '.' . $suffix;
        $res['name'] = $file->getClientFilename();
        $res['url'] =  '/'.$path;
        $res['md5'] = $md5;
        $res['size'] =$file->getSize();
        if(in_array($suffix,['jpg','jpeg','gif','png','ico'])){
            $info = getimagesize($file->getRealPath());
            $res['width'] = $info[0];
            $res['height'] = $info[1];
        }
        $oss->write($path, file_get_contents($file->getRealPath()));

        return $res;
    }

    public function qiniuUpload($file,$suffix,$md5='')
    {
        if (empty($file)) {
            return false;
        }

        $oss = $this->fileSystemFactory->get('qiniu');

        $path = 'uploads/'.date('Ymd') .'/'. $md5 . '.' . $suffix;
        $res['name'] = $file->getClientFilename();
        $res['url'] =  '/'.$path;
        $res['md5'] = $md5;
        $res['size'] =$file->getSize();
        if(in_array($suffix,['jpg','jpeg','gif','png','ico'])){
            $info = getimagesize($file->getRealPath());
            $res['width'] = $info[0];
            $res['height'] = $info[1];
        }

        $oss->writeStream($path, fopen($file->getRealPath(),'r+'));

        return $res;
    }
}